"""
钩子函数，用来定义各类前后置方法
"""
from typing import List

import pytest

from api.base import BaseBuyerApi, BaseSellerApi, BaseAdminApi
from api.buyer.buyer_controller import Select_address, Delete_address_id, Member_address
from api.buyer.login_api import BuyerLoginAPI
from api.manager.manager_api import ManagerAudit, ManagerApi
from api.seller.seller import SellerGoodsAPI, SellerGoodsUnder, SellerGoodsRecycle, SellerGoodsGoods, ManagerSkus
from api.seller.seller import SellerLoginAPI
from common.file_load import read_yml
from common.json_util import extract_json
from common.logger import GetLogger
from common.mysql import DBUtil
from common.redis_util import RedisUtil

"""pytest转码"""
def pytest_collection_modifyitems(
    session: "Session", config: "Config", items: List["Item"]
) -> None:
    # item表示每个测试用例，解决用例名称中文显示问题
    for item in items:
        # item.name = item.name.encode("utf-8").decode("unicodeescape")
        item._nodeid = item._nodeid.encode("utf-8").decode("unicodeescape")

"""初始化log"""
@pytest.fixture(scope="session",autouse=True)
def alogger(worker_id):
    GetLogger.get_logger(worker_id)  # 日志初始化

"""买家获取token"""
@pytest.fixture(scope="session",autouse=True)
def buy_login(worker_id):# 注意这个worker_id指的就是当前的进程id，由pytest-xdist插件提供
    common_info = read_yml("/config/common.yml")
    username_list = common_info["buyerName"]
    password_list = common_info["buyerPassword"]
    if worker_id == "master": # 如果没有采用多进程执行，那么worker_id就是master
        username = username_list[0]
        password = password_list[0]
    else:
        index = int(worker_id[2:])
        username = username_list[index]
        password = password_list[index]
    resp = BuyerLoginAPI(username=username, password=password).request()
    BaseBuyerApi.buy_token = resp.json()["access_token"]
    BaseBuyerApi.uid = resp.json()["uid"]

"""卖家获取token"""
@pytest.fixture(scope="session",autouse=True)
def seller_login():
    common_info = read_yml("/config/common.yml")
    resp = SellerLoginAPI(username=common_info["sellerName"], password=common_info["sellerPassword"]).request()
    BaseSellerApi.seller_token = resp.json()["access_token"]

"""管理员登录"""
@pytest.fixture(scope="session",autouse=True)
def manager_login():
    common_info = read_yml("/config/common.yml")
    resp = ManagerApi(username=common_info["managerName"], password=common_info["managerPassword"]).request()
    BaseAdminApi.admin_token = resp.json()["access_token"]

"""连接数据库"""
@pytest.fixture(scope="session",autouse=True)
def get_db():
    db_info = read_yml("/config/db.yml")["mtxshop"]
    db_util = DBUtil(host=db_info["host"], user=db_info["username"], password=db_info["password"])
    yield db_util
    db_util.close()

"""redis初始化"""
@pytest.fixture(scope="session",autouse=True)
def get_redis():
    redis_info = read_yml("/config/redis.yml")["mtxshop"]
    redis_util = RedisUtil(host=redis_info["host"],pwd=redis_info["password"])
    yield redis_util

"""产品数据准备及清除"""
@pytest.fixture(scope="class",autouse=False)
def goods_data():
    # 卖家发布商品-->管理员审核产品清除产品数据
    resp = SellerGoodsAPI().request()
    # 提取添加商品后得good_id
    goods_id = extract_json(resp.json(),"$.goods_id")
    # 管理员审核商品
    ManagerAudit(goods_ids=[goods_id]).request()
    # 审核通过后，需要想办法得到商品对应的sku_id
    # 使用接口来获取该商品对应的sku_id
    resp = ManagerSkus(goods_id=goods_id).request()
    sku_id = extract_json(resp.json(), "$.[0].sku_id")
    yield sku_id,goods_id
    # 卖家下架商品-->卖家删除商品(回收站)-->卖家彻底删除商品
    SellerGoodsUnder(goods_ids=[goods_id]).request()
    SellerGoodsRecycle(goods_ids=[goods_id]).request()
    SellerGoodsGoods(goods_ids=[goods_id]).request()

# 我们封装一个fixture，主要完成会员地址的判断，如果满20个了，就删除其中一个
@pytest.fixture(scope="class",autouse=False)
def address_data():
    # 调用查询买家地址接口列表
    resp = Select_address().request()
    address = resp.json()
    if len(address) == 20:
        addres_id1 = extract_json(resp.json(),"$.[?(@.def_addr==0)].addr_id")
        # 调用买家删除地址接口
        Delete_address_id(id=addres_id1).request()
        address_id = extract_json(resp.json(),"$.[?(@.def_addr==0).addr_id",index=1)
    elif len(address) == 0: # 如果没有收货地址  那就添加一个
        resp = Member_address().request()
        address_id = extract_json(resp.json(),"$.addr_id")
    else:
        address_id = extract_json(resp.json(),"$.[0].addr_id")
    yield address_id